using System;
using System.Drawing;

namespace MetaViewAnisotropicDiffusion
{
	namespace Matrix
	{
		public class ComplexIntMatrix 
		{
			public IntMatrix real, imag;
			public int XDim
			{
				get{return this.Real.XDim;}
			}

			public int YDim
			{
				get{return this.Real.YDim;}
			}
			public IntMatrix Real
			{
				get{return real;}
			}
			public IntMatrix Imag
			{
				get{return imag;}
			}

			public ComplexIntMatrix(int xdim, int ydim)
			{
				real = new IntMatrix(xdim, ydim);
				imag = new IntMatrix(xdim, ydim);
			}
			public ComplexIntMatrix(int xdim, int ydim, int init)
			{
				real = new IntMatrix(xdim, ydim, init);
				imag = new IntMatrix(xdim, ydim, init);
			}
		}

		public class ComplexDoubleMatrix 
		{
			public DoubleMatrix real, imag;
			public int XDim
			{
				get{return this.Real.XDim;}
			}

			public int YDim
			{
				get{return this.Real.YDim;}
			}
			public DoubleMatrix Real
			{
				get{return real;}
			}
			public DoubleMatrix Imag
			{
				get{return imag;}
			}

			public ComplexDoubleMatrix(int xdim, int ydim)
			{
				real = new DoubleMatrix(xdim, ydim);
				imag = new DoubleMatrix(xdim, ydim);
			}
			public ComplexDoubleMatrix(int xdim, int ydim, double init)
			{
				real = new DoubleMatrix(xdim, ydim, init);
				imag = new DoubleMatrix(xdim, ydim, init);
			}
			public ComplexDoubleMatrix(DoubleMatrix _real, DoubleMatrix _imag)
			{
				real = _real;
				imag = _imag;
			}

			public ComplexDoubleMatrix Clone()
			{
				DoubleMatrix r = this.real.Clone();
				DoubleMatrix i = this.imag.Clone();
				ComplexDoubleMatrix tmp = new ComplexDoubleMatrix(r, i);
				return tmp;
			
			}
			public void UnitScale()
			{
				DoubleMatrix tmp = DoubleMatrix.VectorialAdd(this.Real,this.Imag);
				double max = tmp.Max();
				//init matrix to zero if it is a zero matrix.
				if(max == 0)
				{
					this.Real.Initialize(0.0);
					this.Imag.Initialize(0.0);
				}
				else
				{
					this.Real.DivideValue(max);
					this.Imag.DivideValue(max);
				}
			}

			public void MeanScale()
			{
				DoubleMatrix tmp = DoubleMatrix.VectorialAdd(this.Real,this.Imag);
				double mean = tmp.Average();
				this.Real.DivideValue(mean);
				this.Imag.DivideValue(mean);
			}

			public static ComplexDoubleMatrix operator*(ComplexDoubleMatrix mat1, ComplexDoubleMatrix mat2)
			{
				ComplexDoubleMatrix tmp = new ComplexDoubleMatrix(mat1.XDim, mat1.YDim);
				tmp.real = mat1.Real*mat2.Real-mat1.Imag*mat2.Imag;
				tmp.imag = mat1.Imag*mat2.Real-mat1.Real*mat2.Imag;
				return tmp;
			}

			public static DoubleMatrix operator*(ComplexDoubleMatrix mat1, ComplexDouble comp)
			{
				DoubleMatrix tmp = new DoubleMatrix(mat1.XDim, mat1.YDim);
				for(int i=0;i<mat1.XDim;i++)
				{
					for(int j=0;j<mat1.YDim;j++)
					{
						tmp.data[i,j] = mat1.Real.data[i,j]*comp.real + mat1.Imag.data[i,j]*comp.imag;
					}
				}
				return tmp;
			}
			public static DoubleMatrix operator*(ComplexDouble comp, ComplexDoubleMatrix mat1)
			{
				DoubleMatrix tmp = new DoubleMatrix(mat1.XDim, mat1.YDim);
				for(int i=0;i<mat1.XDim;i++)
				{
					for(int j=0;j<mat1.YDim;j++)
					{
						tmp.data[i,j] = mat1.Real.data[i,j]*comp.real + mat1.Imag.data[i,j]*comp.imag;
					}
				}
				return tmp;
			}


		}

		public class ComplexDouble
		{
			public double real;
			public double imag;
			public ComplexDouble()
			{
			}

			public ComplexDouble(double _real, double _imag)
			{
				real = _real;
				imag = _imag;
			}
		}

	}
}